package com.zzg.datastructure.queue;

/**
 * @Author zhengzg
 * @Date 2022-08-16
 * @Version v1.0
 */
public class CircleArray {

    /**
     * 数组的最大容量
     */
    private int maxSize;

    /**
     * 指向队列的第一个元素，就是说arr[front]就是队列的第一个元素
     */
    private int front;

    /**
     * rear指向队列的最后一个元素的后一个位置，因此空出一个空间作为约定
     */
    private int rear;

    /**
     * 存放数据模拟队列
     */
    private int[] arr;

    public CircleArray(int maxSize){
        this.maxSize = maxSize;
        arr = new int[maxSize];
    }

    // 判断队列是否满
    public boolean isFull(){
        return (rear + 1) % maxSize == front;
    }

    // 判断队列是否为空
    public boolean isEmpty(){
        return front == rear;
    }

    // 添加数据到队列
    public void addQueue(int data){
        if (this.isFull()){
            System.out.println("队列满啦，别加了塞不下了！╥﹏╥...");
            return;
        }

        arr[rear] = data;
        /*
         * 将rear后移，这里必须考虑取模
         * 1. 例如：(0 + 1) % 3 == 1，(2 + 1) % 3 == 0
         * 2. 即尾指针移到索引为2处，再移动将返回起点
         */
        rear = (rear + 1) % maxSize;
    }

    // 获取队列的数据，出队列
    public int getQueue(){
        if (this.isEmpty()){
            throw new RuntimeException("哎，啥也没有！ಥ_ಥ");
        }

        /*
         * 1. 先取出数据，因为现在头指针直接指向元素
         * 2. 再进行取模，使得头指针可以返回起点
         */
        int data = arr[front];
        front = (front + 1) % maxSize;
        return data;
    }

    // 显示队列所有元素
    public void list(){
        // 遍历
        if(this.isEmpty()){
            System.out.println("哎，啥也没有！(￣ε(#￣)");
            return;
        }

        /*
         * 从front开始遍历，遍历元素个数为：front + (rear + maxSize -front) % maxSize
         * 1. rear指针可能出现在front指针前，那么将 rear+maxSize 可以理解为将rear移到front后
         * 2. 将rear+maxSize与front理解为带有刻度的线段，那么rear + maxSize - front相当于获取两刻度之间的值
         * 3. % maxSize,相当于两条刻度线相比，突出的部门即余数为有效的数据个数
         */
        for (int i = 0; i < front + size(); i++) {
            System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
        }

    }

    // 求出当前队列的有效个数
    public int size(){
        return (rear + maxSize - front) % maxSize;
    }

    // 显示列头数据
    public int headQueue(){
        if (this.isEmpty()){
            throw new RuntimeException("哎，啥也没有！(￣ε(#￣)");
        }

        return arr[front];
    }
}
